/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.bean;

import org.ipti.br.tag.bo.*;
import org.ipti.br.tag.entity.*;
import org.ipti.br.tag.entity.enums.Sex;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.ipti.br.tag.bean.lazy.LazyHumanDataModel;
import org.ipti.br.tag.util.LoggerUtil;

/**
 *
 * @author ipti
 */
@Named
@SessionScoped
public class NewActorMB extends AppBaseBean implements Serializable {

    @Inject
    private ActorBO actorBO;
    @Inject
    private HumanBO humanBO;
    @Inject
    private PersonageBO personageBO;
    @Inject
    private UnityBO unityBO;
    @Inject
    private AdditionalInfoTypeBO additionalInfoTypeBO;
    @Inject
    private AddInfoPersonageBO addInfoPersonageBO;
    @Inject
    private AddressBO addressBO;
    @Inject
    private EthnicityBO ethnicityBO;
    @Inject
    private LoginBO loginBO;
    @Inject
    private NationalityBO nationalityBO;
    @Inject
    private NeighborhoodBO neighborhoodBO;
    @Inject
    private StreetBO streetBO;
    @Inject
    private SessionBean sessionBean;
    
    private String mask;
    private Human parent;
    private boolean deactivatedIsNull;
    
    private Unity unity;
    private Login login;
    private Actor actor;
    private Human human;
    private Personage personage;
    private LazyHumanDataModel humanList;
    
    public NewActorMB() {
    }
    
    @PostConstruct
    public void init(){
        personage = personageBO.find(Long.parseLong(getParameter("personage")));
        if(personage == null) redirect("");
        
        human = new Human();
        human.setAddress(new Address(new Neighborhood(), new Street(), new Zipcode()));
        human.setBirthday(Calendar.getInstance());
        
        actor = new Actor();
        actor.setActivated(Calendar.getInstance());
        actor.setDeactivated(Calendar.getInstance());
        actor.setPerson(human);
        actor.setPersonage(personage);
        
        login = new Login(null, null, human);
        humanList = new LazyHumanDataModel();
        
        loadAddInfoList(human);
    }
    
    public void save() {
        try {
            if (personage != null && unity != null) {
                actor.setActivated(unity.getActivated());                   //ativação sempre igual a unidade?
                actor.setDeactivated(unity.getDeactivated());
                actor.setUnity(unity);
            }

            createNewHuman(human);

            actor.setPerson(human);
            actorBO.create(actor);

            String userName = "";
            int precedence = Integer.MAX_VALUE;
            for (AdditionalInfo addInfo : human.getAdditionalInfos()) {
                if (addInfo.getAdditionalInfoType().getPrecedence() < precedence) {
                    userName = addInfo.getValue();
                    precedence = addInfo.getAdditionalInfoType().getPrecedence();
                }
            }

            loginBO.create(userName,human);

            addInfoMessage("newHumanF", "Cadastro realizado com sucesso.", null);
        } catch (Exception ex) {
            addErrorMessage("newHumanF", "Um erro inesperado foi encontrado", null);
            LoggerUtil.log("NewActorMb:save", Level.SEVERE, "Um erro inesperado foi encontrado", ex);
        }
        init();
    }

    public void createParent(Human human) {
        try {
            createNewHuman(human);
            addInfoMessage("newHumanF", "Responsável cadastrado com sucesso.", null);
        } catch (Exception ex) {
            addErrorMessage("newHumanF:actorTab:filiation", "Um erro inesperado foi encontrado", null);
            LoggerUtil.log("Adicionar", Level.SEVERE, "Erro ao criar humano", ex);
        }
    }

    private void createNewHuman(Human human) throws Exception{
        if (validateBirthday() && validateZipcode()) {
            Address address = human.getAddress();

            address.setNeighborhood(
                    neighborhoodBO.createOrRefresh(
                            address.getNeighborhood().getName(),
                            address.getZipcode()));
            address.setStreet(
                    streetBO.createOrRefresh(
                            address.getStreet().getName(),
                            address.getZipcode()));

            human.setAddress(addressBO.createOrRefresh(address));
            
            humanBO.create(human);
        }
    }

    public void prepareNewHuman(Sex sex) {
        parent = new Human();
        parent.setSex(sex);
        parent.setAddress(new Address(new Neighborhood(), new Street(), new Zipcode()));
        parent.setBirthday(Calendar.getInstance());
        parent.setAdditionalInfos(new ArrayList<AdditionalInfo>());
        parent.getAdditionalInfos().add(new AdditionalInfo("", parent, null));
        switch(sex){
            case MALE:
                human.setFather(parent); break;
            case FEMALE:
                human.setMother(parent); break;
            default:
                human.setSponsor(parent);
        }
    }
    
    public boolean canChangeSex(Human human){
        return human != null && (human.getSex() == null || human.getId() != null);
    }

    public void prepareSearch(Sex sex) {
        humanList = new LazyHumanDataModel(sex);
        parent = null;
    }

    public void createActor() {
        if (human != null) {
            try {
                actor.setPersonage(personage);
                actor.setUnity(unity);
                actor.setPerson(human);

                if (deactivatedIsNull) {
                    actor.setDeactivated(null);
                }
                getActorBO().create(actor);

                addInfoMessage("findHumanF", "Cadastro realizado com sucesso.", null);
            } 
            catch (Exception ex) {                
                addErrorMessage("findHumanF", "Um erro foi encontrado", null);
                LoggerUtil.log("NewActorMB:createActor", Level.SEVERE, "Um erro foi encontrado", ex);
            }
        } else {
            addErrorMessage("findHumanF", "Escolha alguém antes de adicionar um cargo", null);
        }
    }

    public boolean validateZipcode() {
        if (human.getAddress().getZipcode() != null) {
            return true;
        } else {
            addErrorMessage("newHumanF:actorTab", "'Endereço' é obrigatório", null);
            return false;
        }
    }

    public boolean validateBirthday() {
        if (human.getBirthday().before(Calendar.getInstance())) {
            return true;
        } else {
            addInfoMessage("newHumanF:actorTab:birthday", "Deve ser anterior à data atual", null);
            return false;
        }
    }

    public void loadAddInfoList(Human human) {
        List<AdditionalInfo> addInfoList = new ArrayList<AdditionalInfo>();
        for (AdditionalInfoType ait : additionalInfoTypeBO.findAddInfoTypesPerPersonage(personage)) {
            AdditionalInfo ai = new AdditionalInfo();
            ai.setAdditionalInfoType(ait);
            ai.setPerson(human);
            addInfoList.add(ai);
        }
        human.setAdditionalInfos(addInfoList);
    }

    public List<AdditionalInfoType> getAddInfoTypeList() {
        return addInfoPersonageBO.findAddInfoTypeWithPersonage();
    }

    public List<Ethnicity> getAllEthnicity(){
        return ethnicityBO.findAllOrder();
    }
    
    public List<Nationality> getAllNationality(){
        return nationalityBO.findAllOrder();
    }
    
    public List<Unity> findUnitys(){
        return unityBO.unityChildrenPerOrganization(
                sessionBean.getLoggedActor().getUnity(),
                personage.getOrganization());
    }

    public Actor getActor() {
        return actor;
    }

    public void setActor(Actor actor) {
        this.actor = actor;
    }

    public ActorBO getActorBO() {
        return actorBO;
    }

    public void setActorBO(ActorBO actorBO) {
        this.actorBO = actorBO;
    }

    public AddInfoPersonageBO getAddInfoPersonageBO() {
        return addInfoPersonageBO;
    }

    public void setAddInfoPersonageBO(AddInfoPersonageBO addInfoPersonageBO) {
        this.addInfoPersonageBO = addInfoPersonageBO;
    }

    public AdditionalInfoTypeBO getAdditionalInfoTypeBO() {
        return additionalInfoTypeBO;
    }

    public void setAdditionalInfoTypeBO(AdditionalInfoTypeBO additionalInfoTypeBO) {
        this.additionalInfoTypeBO = additionalInfoTypeBO;
    }

    public AddressBO getAddressBO() {
        return addressBO;
    }

    public void setAddressBO(AddressBO addressBO) {
        this.addressBO = addressBO;
    }

    public EthnicityBO getEthnicityBO() {
        return ethnicityBO;
    }

    public void setEthnicityBO(EthnicityBO ethnicityBO) {
        this.ethnicityBO = ethnicityBO;
    }

    public Human getHuman() {
        return human;
    }

    public void setHuman(Human human) {
        this.human = human;
    }

    public HumanBO getHumanBO() {
        return humanBO;
    }

    public void setHumanBO(HumanBO humanBO) {
        this.humanBO = humanBO;
    }

    public Human getParent() {
        return parent;
    }

    public void setParent(Human parent) {
        this.parent = parent;
    }

    public LazyHumanDataModel getHumanList() {
        return humanList;
    }

    public void setHumanList(LazyHumanDataModel humanList) {
        this.humanList = humanList;
    }

    public LoginBO getLoginBO() {
        return loginBO;
    }

    public void setLoginBO(LoginBO loginBO) {
        this.loginBO = loginBO;
    }

    public String getMask() {
        return mask;
    }

    public void setMask(String mask) {
        this.mask = mask;
    }

    public NationalityBO getNationalityBO() {
        return nationalityBO;
    }

    public void setNationalityBO(NationalityBO nationalityBO) {
        this.nationalityBO = nationalityBO;
    }

    public NeighborhoodBO getNeighborhoodBO() {
        return neighborhoodBO;
    }

    public void setNeighborhoodBO(NeighborhoodBO neighborhoodBO) {
        this.neighborhoodBO = neighborhoodBO;
    }

    public Personage getPersonage() {
        return personage;
    }

    public void setPersonage(Personage personage) {
        this.personage = personage;
    }

    public PersonageBO getPersonageBO() {
        return personageBO;
    }

    public void setPersonageBO(PersonageBO personageBO) {
        this.personageBO = personageBO;
    }

    public StreetBO getStreetBO() {
        return streetBO;
    }

    public void setStreetBO(StreetBO streetBO) {
        this.streetBO = streetBO;
    }

    public UnityBO getUnityBO() {
        return unityBO;
    }

    public void setUnityBO(UnityBO unityBO) {
        this.unityBO = unityBO;
    }

    public Login getLogin() {
        return login;
    }

    public void setLogin(Login login) {
        this.login = login;
    }

    public SessionBean getSessionBean() {
        return sessionBean;
    }

    public void setSessionBean(SessionBean sessionBean) {
        this.sessionBean = sessionBean;
    }

    public Unity getUnity() {
        return unity;
    }

    public void setUnity(Unity unity) {
        this.unity = unity;
    }

    public boolean isDeactivatedIsNull() {
        return deactivatedIsNull;
    }

    public void setDeactivatedIsNull(boolean deactivatedIsNull) {
        this.deactivatedIsNull = deactivatedIsNull;
    }
}
